package com.small.nacos.core.distributed.distro;

import com.small.nacos.core.cluster.Member;
import com.small.nacos.core.cluster.ServerMemberManager;
import com.small.nacos.core.distributed.distro.component.DistroComponentHolder;
import com.small.nacos.core.distributed.distro.component.DistroDataProcessor;
import com.small.nacos.core.distributed.distro.entity.DistroData;
import com.small.nacos.core.distributed.distro.entity.DistroKey;
import com.small.nacos.core.distributed.distro.task.DistroTaskEngineHolder;
import com.small.nacos.core.distributed.distro.task.delay.DistroDelayTask;
import com.small.nacos.naming.consistency.DataOperation;
import com.small.nacos.naming.consistency.ephemeral.distro.DistroHttpData;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * distro协议
 * @Author zhoujin
 * @Date 2022/11/12 10:11
 */
@Component
public class DistroProtocol {

    private final ServerMemberManager memberManager;

    private final DistroComponentHolder distroComponentHolder;

    private final DistroTaskEngineHolder distroTaskEngineHolder;

    public DistroProtocol(ServerMemberManager memberManager,DistroComponentHolder distroComponentHolder,DistroTaskEngineHolder distroTaskEngineHolder) {
        this.memberManager = memberManager;
        this.distroComponentHolder = distroComponentHolder;
        this.distroTaskEngineHolder= distroTaskEngineHolder;
    }

    /**
     * 同步数据
     * @param distroKey 数据key
     * @param action 执行动作
     * @param delay 延时执行时间
     */
    public void sync(DistroKey distroKey, DataOperation action, int delay) {
        //获取所有集群成员
        List<Member> members = this.memberManager.allMembersWithoutSelf();
        for (Member each : members) {
            //为每一个成员创建一个distroKey
            DistroKey distroKeyWithTarget = new DistroKey(distroKey.getResourceKey(), distroKey.getResourceType(),
                    each.getAddress());

            DistroDelayTask distroDelayTask = new DistroDelayTask(distroKeyWithTarget, action, delay);
            //创建延时任务
            distroTaskEngineHolder.getDelayTaskExecuteEngine().addTask(distroKeyWithTarget, distroDelayTask);
        }
    }

    public boolean onReceive(DistroData distroData) {
        String resourceType = distroData.getDistroKey().getResourceType();
        DistroDataProcessor dataProcessor = distroComponentHolder.findDataProcessor(resourceType);
        if (null == dataProcessor) {
            return false;
        }
        return dataProcessor.processData(distroData);
    }
}
